package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"unsafe"
)

import "C"

var isBigEndian = (*(*[2]uint8)(unsafe.Pointer(&[]uint16{1}[0])))[0] == 0

func main() {}

//export handleData
func handleData(buffer *C.double, samplesCount C.int) {
	// C.GoBytes 似乎不需要copy，已经将buffer给copy过来了
	// []byte转[]double似乎要确定是大端序还是小端序
	data := C.GoBytes(unsafe.Pointer(buffer), C.int(int(samplesCount)*C.sizeof_double))
	count := int(samplesCount)

	extractData := func() []float64 {
		// 从[]byte data中获取样本点数据
		var order binary.ByteOrder
		if isBigEndian {
			order = binary.BigEndian
		} else {
			order = binary.LittleEndian
		}
		reader := bytes.NewReader(data)
		// numbers 接收从data中读取的数字 (真正存放接收的数字的内存位置在numbersFloat32 numbersFloat64中)
		var numbers interface{}
		numbersFloat32 := make([]float32, count)
		numbersFloat64 := make([]float64, count)
		switch C.sizeof_double {
		case 4:
			numbers = numbersFloat32
		case 8:
			numbers = numbersFloat64
		default:
			log.Println("unrecognized float number size (double), size: ", int(C.sizeof_double))
			return nil
		}
		if err := binary.Read(reader, order, numbers); err != nil {
			log.Println("binary.Read failed:", err)
			return nil
		}

		// 样本点数据转float64
		switch C.sizeof_double {
		case 4:
			for i, number := range numbersFloat32 {
				numbersFloat64[i] = float64(number)
			}
		case 8:
			// 已经是用numbersFloat64了，不需要转换
		default:
			log.Println("unrecognized float number size (double)", int(C.sizeof_double))
			return nil
		}

		return numbersFloat64
	}

	queue <- extractData
}

//export initialize
func initialize() {
	if err := loadConfig(); err != nil {
		panic(fmt.Sprintf("加载配置文件失败, 错误: %v", err))
	}
	initQueue()
	// 在给中心服务器发送数据的时候才会初始化websocket
	if err := initDB(); err != nil {
		panic(fmt.Sprintf("无法连接MongoDB数据库，错误：%v", err))
	}
	initWebServer()
	if conf.Mock {
		// 在go中模拟数据，此时会一直在mockData中跑，不会结束initialize进入C程序
		mockData()
	}
}

//export cleanUp
func cleanUp() {
	closeWebsocket()
	closeDB()
}
